# 随机选择两张锚点照片，让人类判断是正样本还是负样本
# 由于知道真值了，所以本程序实现的是上述过程的模拟，并不需要人类真正判断
import os
import random
import numpy as np

supplement_pair_num = 66666
supplementPath = 'E:/Research/2020ContrastiveLearningForSceneLabel/Data/20210329ExperimentData/round2/supplement%dPairPosNeg.txt'%(supplement_pair_num)
supplementPath_all = 'E:/Research/2020ContrastiveLearningForSceneLabel/Data/20210329ExperimentData/round2/supplement%dPairPosNeg_all.txt'%(supplement_pair_num)

anchor_referenceLabel_path = 'E:/Research/2020ContrastiveLearningForSceneLabel/Data/20210329ExperimentData/round2/anchorReferenceLabel_method2_exp2.txt'
anchorImg_path = 'E:/Research/2020ContrastiveLearningForSceneLabel/Data/20210329ExperimentData/round2/anchorImgs_method2_exp2/anchorImgs'

# 加载数据，获得锚点索引、各个锚点的参考标签
anchor_idxes = []
for _,_, anchor_idxes in os.walk(anchorImg_path):
    break
anchor_idxes = [int(i[:-4]) for i in anchor_idxes]
anchor_idxes.sort()

f = open(anchor_referenceLabel_path, 'r')
lines = f.readlines()
f.close()
labels = [int(i.split()[0]) for i in lines]

anchor_num = len(anchor_idxes)

background_relationship_matrix = np.zeros((anchor_num, anchor_num),dtype=int)
for i in range(anchor_num):
    for j in range(anchor_num):
        if i == j or j == (i+1)%anchor_num or j == (i-1 + anchor_num) % anchor_num:
            if i == j:
                background_relationship_matrix[i][j] = 2
            else:
                background_relationship_matrix[i][j] = -1

relationship_matrix = background_relationship_matrix.copy() # 这俩矩阵都是对称阵，初始化和更新的时候需要注意点
unknow_relationship_num = anchor_num * anchor_num - 3 * anchor_num

def update_matrix(relationship_matrix, background_relationship_matrix, i, j, relationship): # 矩阵式是对称阵， 更新的时候注意点
    relationship_matrix[i][j] = relationship
    relationship_matrix[j][i] = relationship

    def set_positive(x,y):
        if background_relationship_matrix[x][y] != 0:
            return
        background_relationship_matrix[x][y] = 1
        background_relationship_matrix[y][x] = 1
        global unknow_relationship_num
        unknow_relationship_num -= 2
        for i in range(anchor_num):
            if background_relationship_matrix[i][y] == 1:
                set_positive(x,i)
            if background_relationship_matrix[i][y] == -1:
                set_negative(x, i)
        for i in range(anchor_num):
            if background_relationship_matrix[x][i] == 1:
                set_positive(y, i)
            if background_relationship_matrix[x][i] == -1:
                set_negative(y, i)

    def set_negative(x,y):
        if background_relationship_matrix[x][y] != 0:
            return
        background_relationship_matrix[x][y] = -1
        background_relationship_matrix[y][x] = -1
        global unknow_relationship_num
        unknow_relationship_num -= 2
        for i in range(anchor_num):
            if background_relationship_matrix[i][y] == 1:
                set_negative(x,i)
        for i in range(anchor_num):
            if background_relationship_matrix[x][i] == 1:
                set_negative(y,i)
    
    if relationship == 1:
        set_positive(i,j)
    if relationship == -1:
        set_negative(i,j)
        

def sample_index(background_relationship_matrix):
    seed = np.random.uniform(0, unknow_relationship_num)
    seed = int(seed)
    i = j = 0
    cur_idx = 0
    for i in range(anchor_num):
        for j in range(anchor_num):
            if background_relationship_matrix[i][j] == 0:
                if cur_idx == seed:
                    return i,j
                cur_idx += 1

def get_relationship(i,j):
    if labels[i] == labels[j]:
        relationship = 1
    else:
        relationship = -1
    return relationship

def write_to_file(relationship_matrix, supplementPath):
    f = open(supplementPath,'w')
    for i in range(anchor_num):
        pos_list = []
        neg_list = []
        for j in range(anchor_num):
            if i == j or j == (i+1)%anchor_num or j == (i-1 + anchor_num) % anchor_num:
                continue
            if relationship_matrix[i][j] == 1:
                pos_list.append(anchor_idxes[j])
            if relationship_matrix[i][j] == -1:
                neg_list.append(anchor_idxes[j])
        if pos_list == [] and neg_list == []:
            continue
        f.write('%d: '%anchor_idxes[i])
        for idx in pos_list:
            f.write('%d '%idx)
        f.write(': ')
        for idx in neg_list:
            f.write('%d '%idx)
        f.write('\n')
    f.close()

alerting_supplement_num = 0
def check():
    for i in range(anchor_num):
        for j in range(anchor_num):
            if i == j or j == (i+1)%anchor_num or j == (i-1 + anchor_num) % anchor_num or background_relationship_matrix[i][j] == 0:
                continue
            if labels[i] == labels[j]:
                relationship = 1
            else:
                relationship = -1
                if (labels[i] == 3 and labels[j] != 3) or (labels[j] == 3 and labels[i] != 3):
                    global alerting_supplement_num
                    alerting_supplement_num += 1
            if background_relationship_matrix[i][j] != relationship:
                print('Error! Program exit.')
                exit()

def main():
    # while unknow_relationship_num:
    for i in range(160):
        x,y = sample_index(background_relationship_matrix)
        relationship = get_relationship(x,y)
        update_matrix(relationship_matrix, background_relationship_matrix, x,y, relationship)
    check()
    write_to_file(background_relationship_matrix, supplementPath_all)
    write_to_file(relationship_matrix, supplementPath)
    print('Alerting supplemetn num: %d'%int(alerting_supplement_num/2))


if __name__ == '__main__':
    main()